package com.odianyun.hello.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.trang.typehandlers.util.EncryptUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.netflix.config.ConfigurationManager;
import com.odianyun.db.mybatis.*;
import com.odianyun.db.query.PageVO;
import com.odianyun.hello.constant.CommonConstant;
import com.odianyun.hello.mapper.*;
import com.odianyun.hello.model.PO.*;
import com.odianyun.hello.model.VO.CodeVO;
import com.odianyun.hello.model.VO.SoReturnVO;
import com.odianyun.hello.service.CodeService;
import com.odianyun.hello.service.SoService;
import com.odianyun.hello.model.VO.SoVO;
import com.odianyun.hello.service.SoTypeService;
import com.odianyun.project.base.IEntity;
import com.odianyun.project.query.PageQueryArgs;
import com.odianyun.project.query.QueryArgs;
import com.odianyun.project.query.QueryParamBuilder;
import com.odianyun.project.support.base.db.EQ;
import com.odianyun.project.support.base.db.Q;
import com.odianyun.project.support.base.service.OdyEntityService;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.omg.CORBA.PRIVATE_MEMBER;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import sun.security.krb5.EncryptedData;

@Service
public class SoServiceImpl extends OdyEntityService<SoPO, SoVO, PageQueryArgs, QueryArgs, SoMapper> implements SoService {
    @Resource
    private SoMapper soMapper;
    @Resource
    private SoPackageMapper soPackageMapper;
    @Resource
    private SoPackageItemMapper soPackageItemMapper;
    @Resource
    private SoReturnItemMapper soReturnItemMapper;
    @Resource
    private SoItemMapper soItemMapper;
    @Resource
    private CodeService codeService;
    @Resource
    private SoTypeService soTypeService;
    @Resource
    private SoService service;
    @Resource
    private SoReturnMapper soReturnMapper;

    @Override
    protected SoMapper getMapper() {
        return soMapper;
    }

    private Map<String , String> getCode(String pool , String category){
        List<CodeVO> codeVOList = codeService.listByCategory(pool,category);
        return codeVOList.stream().collect(Collectors.toMap(CodeVO::getCode, CodeVO::getName));
    }

    //对出参进行设置
    @Override
	protected void afterListPage(PageVO<? extends IEntity> pageVO) {
        if (CollectionUtils.isEmpty(pageVO.getList())){
            return;
        }

        Map<String , String> soTypeMap = soTypeService.getSoType();
        Map<String , String> orderStatusMap = codeService.getOrderStatus();
        Map<String , String> sysChannelMap = this.getCode(CommonConstant.CODE_POOL_DEFAULT , CommonConstant.CODE_CATEGORY_SYS_CHANNEL);

        pageVO.getList().forEach(item ->{
            SoVO soVO = (SoVO) item;
            soVO.setOrderStatusName(orderStatusMap.get(soVO.getOrderStatus()));
            soVO.setSoTypeName(soTypeMap.get(soVO.getOrderType()));
            soVO.setSysChannelName(sysChannelMap.get(soVO.getSysSource()));
//            soVO.setGoodReceiverMobile(EncryptUtil.decrypt(soVO.getGoodReceiverMobile()));
//            soVO.setGoodReceiverAddress(EncryptUtil.decrypt(soVO.getGoodReceiverAddress()));
        });
	}

    @Override
    public PageVO<SoVO> ListPageByMore(PageQueryArgs args, String[] selectSoItemFiled) {
        AbstractQueryFilterParam<?> param = toQuery(args,selectSoItemFiled);
        return super.listPage(param, args.getPage(), args.getLimit());
    }

    @Override
    public Map<String,Long> getStatus(QueryArgs args) {
        EntityQueryParam entityQueryParamSoItem = new EntityQueryParam(SoItemPO.class,"soi");
        EntityQueryParam entityQueryParamSr = new EntityQueryParam(SoReturnPO.class,"sr");
        EntityQueryParam entityQueryParamSo = new EntityQueryParam(SoPO.class,"s");
        List<CodeVO> codeList = codeService.getStatus();
        System.out.println(JSONObject.toJSONString(codeList));
        Map<String, Object> filters = args.getFilters();
        args.setFilters(filters);
        args.getBuilder().ignore("code","productCname","orderRemarkUser");
        entityQueryParamSo.exists(entityQueryParamSr).on("orderCode","orderCode");
        //关联查询
        EntityQueryParam s = args.getBuilder().buildParam(new EQ(SoPO.class, "s")).withResultClass(SoVO.class);
        if (null != filters.get("code") && null != filters.get("productCname")){
            s.join(entityQueryParamSoItem).on("orderCode","orderCode");
        }
        if (null != filters.get("code")){
            entityQueryParamSoItem.eq("soi.code",filters.get("code"));
        }
        if (null != filters.get("productCname")){
            entityQueryParamSoItem.like("soi.productCname",filters.get("productCname"));
        }
        //模糊查询
//        String orderRemarkUser = (String) args.get("orderRemarkUser");
//        args.getConverter()
//                .withFilterConfig("orderRemarkUser", StringUtils.isEmpty(orderRemarkUser)
//                        ? Filter.Operator.NOTNULL: Filter.Operator.LIKE);
        if(null != filters.get("orderRemarkUser")){
            s.like("orderRemarkUser",filters.get("orderRemarkUser"));
        }
        List<SoVO> listVo = service.list(s);
        Map<Integer, Long> groupSoMap = listVo.stream().collect(Collectors.groupingBy(SoVO::getOrderStatus , Collectors.counting()));

        for (CodeVO codeVO : codeList){
            codeVO.setCount(groupSoMap.getOrDefault(Integer.parseInt(codeVO.getCode()),0L));
        }
        Map<String,Long> map = new HashMap<>();
        for(int i = 0 ; i < codeList.size() ; i++ ){
            CodeVO codeVO = codeList.get(i);
            map.put(codeVO.getName(),codeVO.getCount());
        }
        return map;
    }

    @Override
    public void updateStatus(String orderCode) {
        /*在code中查询order_status（1070已签收）*/
        Integer sCode = codeService.getOrderCodeByName("已签收");
        /*在code中查询package_status（3040）*/
        Integer pCode = codeService.getPackageCodeByName("已送达");
        /*在code中查询item_status（1070）*/
        Integer siCode = codeService.getSoItemCodeByName("已签收");

        /*------------------------------------------更新包裹so_package的状态----------------------------------------------*/

        EntityQueryParam entityQueryParamSp = new EntityQueryParam(SoPackagePO.class,"sp");
        entityQueryParamSp.eq("orderCode",orderCode);
        entityQueryParamSp.selects("packageStatus");
        SoPackagePO soPackagePO=soPackageMapper.get(entityQueryParamSp);
        //System.out.println(JSONObject.toJSONString(so));
        //System.out.println(JSONObject.toJSONString(soPackagePO));
        //System.out.println(sCode+"------ "+pCode);
        SoPackagePO soPackagePO1 = new SoPackagePO();
        soPackagePO1.setPackageStatus(pCode);//设置包裹状态为已送达(3040)
        UpdateParam updateParamSpi = new UpdateParam(soPackagePO1,true);
        updateParamSpi.eq("orderCode",orderCode);
        //如果包裹状态小于已送达（3040），则更新包裹状态为已送达
        if(soPackagePO.getPackageStatus() < pCode){
            soPackageMapper.update(updateParamSpi);
            //System.out.println("-----"+row+"------");
        }
/*------------------------------------------更新so_item的状态----------------------------------------------*/
        QueryParam queryParamSpi = new Q("productItemOutNum");
        QueryParam queryParamSri = new Q("returnProductItemNum");
        QueryParam queryParamSi = new Q("productItemNum","itemStatus");
        queryParamSpi.eq("orderCode",orderCode);
        queryParamSri.eq("orderCode",orderCode);
        queryParamSi.eq("orderCode",orderCode);
        List<SoPackageItemPO> listSpi =soPackageItemMapper.list(queryParamSpi);
        List<SoReturnItemPO> listSri =soReturnItemMapper.list(queryParamSri);
        List<SoItemPO> listSi =soItemMapper.list(queryParamSi);
//      System.out.println(JSONObject.toJSONString(listSpi));
//      System.out.println(JSONObject.toJSONString(listSri));
//      System.out.println(JSONObject.toJSONString(listSi));
        Iterator iteratorSpi = listSpi.iterator();
        BigDecimal sumSpi = new BigDecimal(0);
        while (iteratorSpi.hasNext()){
            SoPackageItemPO spiPO= (SoPackageItemPO) iteratorSpi.next();
            BigDecimal numSpi=spiPO.getProductItemOutNum();
            sumSpi=sumSpi.add(numSpi);//计算包裹明细表出库数量总数
            //System.out.println(spiPO.getProductItemOutNum());
        }
        //System.out.println(sumSpi);

        //遍历listSri
        BigDecimal sumSri = new BigDecimal(0);
        for (int i = 0 ; i<listSri.size() ; i++) {
            SoReturnItemPO soReturnItemPO = listSri.get(i);
            BigDecimal numSri = soReturnItemPO.getReturnProductItemNum();
            sumSri = sumSri.add(numSri);//计算售后明细的总数
        }
        //System.out.println(sumSri);

        //遍历listSi
        List<Integer> listItemStatus = new ArrayList<>();//用于第三问，保存了订单明细表的订单状态
        Iterator iteratorSi = listSi.iterator();
        BigDecimal sumSi = new BigDecimal(0);
        while (iteratorSi.hasNext()){
            SoItemPO siPO= (SoItemPO) iteratorSi.next();
            BigDecimal numSi=siPO.getProductItemNum();
            sumSi=sumSi.add(numSi);//计算订单明细表总数

            Integer itemStatus = siPO.getItemStatus();//获取订单明细表中订单的状态item_status
            listItemStatus.add(itemStatus);//将获取到的状态保存到集合中
            //System.out.println(itemStatus);
        }
        //System.out.println(JSONObject.toJSONString(listItemStatus));
        //System.out.println(sumSi);

        SoItemPO soItemPO = new SoItemPO();
        UpdateParam updateParamSi = new UpdateParam(soItemPO,true);
        updateParamSi.eq("orderCode",orderCode);
        soItemPO.setItemStatus(siCode);
        if(sumSi.equals(sumSpi.add(sumSri))){
            soItemMapper.update(updateParamSi);
        }
        /*------------------------------------------so_item的状态都为已签收时，更新订单状态为1070----------------------------------------------*/

        SoPO soPO = new SoPO();
        UpdateParam updateParamSo = new UpdateParam(soPO,true);
        updateParamSo.eq("orderCode",orderCode);
        soPO.setOrderStatus(sCode);

        /*判断so_item的所有状态是否都是已签收，去重后判断是否是已签收*/
        List list = listItemStatus.stream().distinct().collect(Collectors.toList());
        System.out.println(list.get(0));

        if(list.size()==1 && list.get(0).equals(siCode)){
            soMapper.update(updateParamSo);
        }
    }


    /*------------------------------------------------------------------------------------------------------------------------------------*/
    protected  EntityQueryParam toQuery(QueryArgs args , String[] selectSoItemFiled){
        args.getConverter().ignore("code","productCname","orderRemarkUser");
        String orderRemarkUser = (String) args.get("orderRemarkUser");
        if(orderRemarkUser != null){
            args.getConverter().withFilterConfig("orderRemarkUser",
                    StringUtils.isEmpty(orderRemarkUser) ? Filter.Operator.NOTNULL: Filter.Operator.LIKE);
        }
        //So表查询
        EntityQueryParam so = args.getConverter().buildParam(new EQ(entityClass,"so").withResultClass(resultClass));
        Object code =   args.get("code");
        Object productCname = args.get("productCname");
        if (code != null || productCname != null || selectSoItemFiled != null){
            //关联soItem
            EntityQueryParam si = new EQ(SoItemPO.class,"si").withSkipNullValueFilter(true);
            if (selectSoItemFiled != null){
                so.join(si).on("orderCode","orderCode");
                si.selects(selectSoItemFiled).select("id","soItemId");
            }else {
                so.exists(si).on("orderCode","orderCode");
            }
            if(code != null){
                si.eq("code",code);
            }
            if(productCname != null){
                si.like("productCname",productCname);
            }
        }
        //是否存在售后
        Boolean existReturn = args.get("existReturn",Boolean.class);
        if(existReturn != null && existReturn.booleanValue()){
            so.exists(new EQ(SoReturnPO.class,"sr").withSkipNullValueFilter(true));
        }
        return so.desc("orderCreateTime");
    }




    @Override
    public List<Map<String, Object>> getCountByStatus(QueryArgs args) {
        Map<String, String> statusMap = codeService.getOrderStatus();
        args.getConverter().withSkipSelectFields();
        EntityQueryParam q =this.toQuery(args,null);
        //查询so表数量
        q.select("count(${id})","count")
                .select("orderStatus","code");
        q.in("orderStatus",statusMap.keySet());
        q.groupBy("orderStatus").withSelectAsAlias();

        List<Map<String, Object>> listStatusCount = soMapper.listForMap(q);
        Map<String,Object> countMap = Maps.newHashMap();
        System.out.println(JSONObject.toJSONString(listStatusCount));
        listStatusCount.forEach(item->{
            countMap.put(item.get("code").toString(),item.get("count"));
        });
        List<Map<String , Object>> result = Lists.newArrayListWithExpectedSize(countMap.size());
        statusMap.forEach((k , v)->{
            Map<String,Object> resultMap = Maps.newHashMap();
            resultMap.put("code",k);
            resultMap.put("name",v);
            resultMap.put("count", countMap.get(k) != null ? countMap.get(k) : 0);
            result.add(resultMap);
        });
        System.out.println(JSONObject.toJSONString(result));
        return result;
    }


    @Override
    public void updateStatus(){

    }
}
